package com.example.audio_test.utils

import android.media.MediaCodec
import android.media.MediaExtractor
import android.media.MediaFormat
import android.view.Surface
import java.io.File
import java.io.FileInputStream
import java.io.IOException


/**
 *视频解码播放线程
 *
 * @author : Kun
 * @date : 2021/6/24
 * @time : 10:49
 */
class VideoMediaCodecWorker(private val surface: Surface, private val filePath: String) : Thread() {

    private var mediaExtractor = MediaExtractor()
    private var mediaCodec: MediaCodec? = null

    private var isStop = false

    override fun run() {
//        super.run()
        try {
            val inputSystem = FileInputStream(File(filePath))
            mediaExtractor.setDataSource(inputSystem.fd)

        } catch (e: IOException) {
            e.printStackTrace()
        }

        for (i in 0 until mediaExtractor.trackCount) {
            val mediaFormat = mediaExtractor.getTrackFormat(i)
            val mine = mediaFormat.getString(MediaFormat.KEY_MIME)
            if (mine!!.startsWith("video/")) {
                //选中视频轨道
                mediaExtractor.selectTrack(i)
                try {
                    mediaCodec = MediaCodec.createDecoderByType(mine)
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                //配置解码器
                mediaCodec!!.configure(mediaFormat, surface, null, 0)
            }
        }
        //没找到视频轨道，直接返回
        mediaCodec?.start() ?: return

        //结束标志
        var isEnd = false

        //用于对准视频时间戳
        var startMs = System.currentTimeMillis()

        while (!isStop) {
            if (!isEnd) {
                //读取视频
                //获取一个可用的输入索引

                var inputIndex = -1
                try {
                    inputIndex = mediaCodec!!.dequeueInputBuffer(1000)

                    if (inputIndex > 0) {
                        //获取buffer
                        val inputBuffer = mediaCodec!!.getInputBuffer(inputIndex) ?: continue
                        //把视频写入到输入buffer中
                        val sampleSize = mediaExtractor.readSampleData(inputBuffer, 0)
                        if (sampleSize < 0) {
                            //视频已经结束
                            isEnd = true
                            mediaCodec!!.queueInputBuffer(
                                inputIndex,
                                0,
                                0,
                                0,
                                MediaCodec.BUFFER_FLAG_END_OF_STREAM
                            )
                        } else {
                            //编码视频数据
                            mediaCodec!!.queueInputBuffer(
                                inputIndex,
                                0,
                                sampleSize,
                                mediaExtractor.sampleTime,
                                0
                            )
                            //移动至下一个样本
                            mediaExtractor.advance()
                        }
                    }
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                }
            }

            //bufferInfo 包含范围偏移和大小
            val bufferInfo = MediaCodec.BufferInfo()
            //获取可用输出的index
            var outputIndex = 0
            try {
                outputIndex = mediaCodec!!.dequeueOutputBuffer(bufferInfo, 1000)

                when (outputIndex) {
                    MediaCodec.INFO_OUTPUT_FORMAT_CHANGED -> {
                        //buffer 的格式发生变化，需指向新的buffer格式
                    }
                    MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED -> {
                        //buffer 的格式发生变化，需指向新的buffer格式
                    }
                    MediaCodec.INFO_TRY_AGAIN_LATER -> {
                        //超时
                    }
                    else -> {
                        sleepRender(bufferInfo, startMs)
                        mediaCodec!!.releaseOutputBuffer(outputIndex, true)
                    }
                }
                //视频播放完成
                if ((bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    break
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        }

        try {
            mediaCodec!!.stop()
            mediaCodec!!.release()
            mediaExtractor.release()
        } catch (e: IllegalStateException) {
            e.printStackTrace()
        }
    }

    /**
     * 休眠时间，保持帧率
     */
    fun sleepRender(bufferInfo: MediaCodec.BufferInfo, time: Long) {
        //单位是毫秒，buffInfo的时间为微秒
        val sleepTime = bufferInfo.presentationTimeUs / 1000 - (System.currentTimeMillis() - time)
        try {
            sleep(sleepTime)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun stopPlay() {
        isStop = true
    }
}